-- Glowny kontroler - przyjmuje dane 8-bitowe, formuje z nich 128-bitowe bloki,
-- przekazuje do wolnych jednostek obliczeniowych, odbiera bloki i wysyla je w formacie 8-bitowym
-- Przystosowany do wspolpracy z portem szeregowym

-- push - przekazanie aktualnego datain do bufora
-- pop - pobranie ostatniego obliczonego bajtu i przejscie do nastepnego
-- mode - wybor miedzy koderem a dekoderem
-- loadkey - pozwala na zmiane klucza

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity controller is
	 generic ( entities : natural := 2 );	-- ilosc sterowanych koderow/dekoderow
    port ( datain : in std_logic_vector(7 downto 0);
           dataout : out std_logic_vector(7 downto 0);
           clk, rst, push, pop, mode, loadkey : in std_logic);
end controller;

architecture Behavioral of controller is
	-- Sygnaly laczace dane
	signal start_signals, finish_signals : std_logic_vector(0 to entities - 1);
	signal buffer_in, buffer_out, key : std_logic_vector(127 downto 0);
	type buffers is array (0 to entities - 1) of std_logic_vector (127 downto 0);
	signal datain_buffers, dataout_buffers : buffers;
	
	-- Okresla do/z ktorego kodera podawane/odbierane sa teraz dane
	shared variable input_entity, output_entity : integer range 0 to entities - 1 := 0;
	-- Okresla ktory bajt zapisywany/wysylany
	shared variable input_byte, output_byte : integer range 0 to 15 := 0;
begin
	Gen_Coders:
		for i in 0 to entities - 1 generate
			Coders: entity work.coder(Structural)
				port map (start => start_signals(i),
							 clk => clk,
							 rst => rst,
							 datain => datain_buffers(i),
							 key => key,
							 dataout => dataout_buffers(i),
							 finish => finish_signals(i));
		end generate Gen_Coders;
		
		-- TODO Gen_Decoders
		
		-- Obsluga bufora wejsciowego
		process(clk)
		begin
			if (rising_edge(clk)) then
				if (push = '1') then
					buffer_in((127 - (input_byte * 8)) downto (127 - ((input_byte + 1) * 8 - 1))) <= datain;
					
					-- Przesuniecie wskaznika na kolejne miejsce w buforze
					input_byte := (input_byte + 1) mod 16;
					
					if (input_byte = 0) then
						-- Przejscie do kolejnej jednostki obliczeniowej
						input_entity := (input_entity + 1) mod entities;
						
						-- Uruchomienie przetwarzania
						start_signals((input_entity - 1) mod entities) <= '1';
					end if;
				else
					start_signals((input_entity - 1) mod entities) <= '0';
					-- Zgaszenie sygnalu startu poprzedniej jednostki obliczeniowej
				end if;
			end if;
		end process;
		
		-- Multiplekser laczacy bufor wejsciowy z danymi lub kluczem
		process(clk)
		begin
			if (rising_edge(clk)) then
				if (loadkey = '1') then
					-- Ladowanie klucza
					key <= buffer_in;
				else
					-- Ladowanie danych
					datain_buffers(input_entity) <= buffer_in;
				end if;
			end if;
		end process;
		
		-- Obsluga bufora wyjsciowego
		process(clk)
		begin
			if (rising_edge(clk)) then
				if (pop = '1') then
					-- Przekazywanie obliczonego bajtu na wyjscie
					
				end if;
			end if;
		end process;

end Behavioral;

